#ifndef __DATE_TIME_H__
  #define __DATE_TIME_H__

#include <string>
#include <ctime>
#include <cstring>

#include "general_date_time.h"

using namespace std;

#define DATE_TIME_FORMAT "%Y-%M-%D %h:%m:%s" // use %ms for millisecond(s)
#define DATE_FORMAT "%Y-%M-%D"
#define TIME_FORMAT "%h:%m:%s" // use %ms for millisecond(s)

enum time_unit { millisecond = 0, second, minute, hour };

//////////////

//! A class to hold date & time values

/*!
This class is suitable for date & time representation. Also addition and subtraction and comparison operations
are supported.

Implementation date: 2007

Usage:

\code
date_time dt;
cout << dt.to_string() << endl; // current date
cout << dt.to_string(DATE_TIME_FORMAT) << endl; // current date & time
cout << dt.to_string("Year: %Y") << endl; // current year

date_time dt1(1); // one year
date_time dt2(1, 1); // one year and one month

bool b = dt2 > dt1;
\endcode
*/

class date_time {
private:
  general_date date_value;
  general_time time_value;

  void split_values(const string &input, unsigned short output[3], char separator);
  void process_date_and_time(const string &input, char date_separator, char time_separator);
  void process_date(const string &input, char date_separator);
  void process_time(const string &input, char time_separator);

public:
  //! returns the total time in time_unit (could be millisecond, second, minute or hour)
  unsigned long long get_total_time(time_unit unit) const;

  //! returns the general_date
  const general_date &get_date() const;

  //! sets the date (does not change time values)
  void set_date(unsigned short year, unsigned short month, unsigned short day);

  //! sets the general_date (does not change time values)
  void set_date(const general_date &gd);

  //! returns the general_time
  const general_time &get_time() const;

  //! sets the time (does not change date values)
  void set_time(unsigned short hour, unsigned short minute, unsigned short second, unsigned short millisecond);

  //! sets the general_time (does not change date values)
  void set_time(const general_time &gt);

  //! sets the date and/or time
  /*!
  accepted formats are:
  "YYYY-MM-DD hh:mm:ss"
  "YYYY-MM-DD"
  "hh:mm:ss"
  */
  void set_date_time(const string &input, char date_separator = '-', char time_separator = ':');

  //! returns the string representation of the object
  string to_string(string format = DATE_FORMAT) const;

  //! plus operator
  date_time operator+(const date_time &t) const;

  //! minus operator
  date_time operator-(const date_time &t) const;

  //! assignment operator
  date_time &operator=(const date_time &t);

  //! greater than operator
  bool operator>(const date_time &t) const;

  //! greater than or equal operator
  bool operator>=(const date_time &t) const;

  //! less than operator
  bool operator<(const date_time &t) const;

  //! less than or equal operator
  bool operator<=(const date_time &t) const;

  //! equal to operator
  bool operator==(const date_time &t) const;

  //! sets the current date_time object to the current date and time
  /*!
  if the system date is a date before midnight, January 1, 1970, then this method does nothing
  */
  void set_to_current_date_and_time();

  //! default constructor: initializes with current date & time
  date_time();

  //! copy constructor
  date_time(const date_time &dt);

  //! constructor
  date_time(unsigned short year, unsigned short month = 0, unsigned short day = 0, unsigned short hour = 0, unsigned short minute = 0, unsigned short second = 0, unsigned short millisecond = 0);

  //! destructor (non-virtual: please do not inherit from this class)
  ~date_time();
}; // class date_time

#endif
